package gsw.tool.pluggable.hook.hook;

import java.lang.reflect.Field;
import java.lang.reflect.Proxy;

import gsw.tool.pluggable.hook.handler.BaseHandlerClass;
import gsw.tool.pluggable.hook.handler.HandlerActivityManager;

/**
 * Hook系统的ActivityManager，拦截它的startActivity()，将跳转目标设为代理组件，从而跳过PMS检查。
 * 步骤如下：
 * 1.通过反射获取系统的ActivityManagerNative的gDefault属性；
 * 2.通过反射gDefault，获取IactivityManager属性
 * 3.使用动态代理的IactivityManager对象，替换gDefault的IactivityManager属性
 */
public class HookActivityManager extends BaseHookProxy {

    @Override
    protected BaseHandlerClass createHookHandle() {
        return new HandlerActivityManager();
    }

    @Override
    public void onInit(ClassLoader classLoader) {
        try {
            /**
             * 通过反射获取系统的ActivityManagerNative的gDefault属性
             */
            Class<?> ActivityManagerNativecls = Class.forName("android.app.ActivityManagerNative");
            Field gDefault = ActivityManagerNativecls.getDeclaredField("gDefault");
            gDefault.setAccessible(true);
            //得到ActivityManagerNative的gDefault属性
            Object defaltValue = gDefault.get(null);

            //mInstance对象
            Class<?> SingletonClass = Class.forName("android.util.Singleton");
            Field mInstance = SingletonClass.getDeclaredField("mInstance");
            //还原 IactivityManager对象  系统对象
            mInstance.setAccessible(true);
            Object iActivityManagerObject = mInstance.get(defaltValue);

            //保存系统对象
            setRealObj(iActivityManagerObject);

            Class<?> IActivityManagerIntercept = Class.forName("android.app.IActivityManager");
            //动态代理iActivityManagerObject，对其进行扩展，增加意图替换的逻辑
            Object oldIactivityManager = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader()
                    , new Class[]{IActivityManagerIntercept}
                    , this);

            //使用动态代理的IactivityManager对象，替换gDefault的IactivityManager属性
            mInstance.set(defaltValue, oldIactivityManager);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
